<template>
  <div class="api-common-wrap">
    <a-form-model :model="form"
                  :rules="rules"
                  ref="ruleForm"
                  :label-col="labelCol"
                  :wrapper-col="wrapperCol"
                  layout="horizontal">
      <a-divider orientation="left">接口请求</a-divider>
      <!-- 接口地址 -->
      <a-form-model-item label="接口地址"
                         prop="interfaceAddr">
        <a-tooltip>
          <template slot="title">
            输入后回车可自动解析查询参数和path
          </template>
          <a-input v-model="form.interfaceAddr"
                   placeholder="system/get/{id}"
                   @pressEnter="onParseParams"
                   :addon-before="connectorData && connectorData.baseUrl"></a-input>
        </a-tooltip>
      </a-form-model-item>
      <!-- 请求协议 -->
      <a-form-model-item label="请求协议"
                         prop="requestMethod">
        <a-radio-group v-model="form.requestMethod"
                       @change="requestMethodChange">
          <a-radio value="1">GET</a-radio>
          <a-radio value="2">POST</a-radio>
        </a-radio-group>
      </a-form-model-item>
      <div style="width: 90%;margin: 10px auto 0 auto">
        <a-button type="primary"
                  size="small"
                  @click="onParseJson('requestObject')">
          <a-icon type="plus-square" />通过JSON生成
        </a-button>
        <a-tabs v-model="activeTabKey">
          <a-tab-pane key="1">
            <span slot="tab">
              <a-tooltip placement="top"
                         :mouseEnterDelay="0.3">
                <template slot="title">
                  <span>解析请求的所有参数字段，添加相应字段描述，例：username:用户名</span>
                </template>
                <span>参数</span>
              </a-tooltip>
            </span>
          </a-tab-pane>
          <a-tab-pane key="2">
            <span slot="tab">
              <a-tooltip placement="top"
                         :mouseEnterDelay="0.3">
                <template slot="title">
                  <span>请求的消息头</span>
                </template>
                <span>消息头（headers）</span>
              </a-tooltip>
            </span>
          </a-tab-pane>
          <a-tab-pane key="3"
                      v-if="form.requestMethod != '2'">
            <span slot="tab">
              <a-tooltip placement="top"
                         :mouseEnterDelay="0.3">
                <template slot="title">
                  <span>GET请求解析的url路径参数</span>
                </template>
                <span>path参数</span>
              </a-tooltip>
            </span>
          </a-tab-pane>
        </a-tabs>
        <a-table :columns="requestTableColumns[activeRequestKey]"
                 :data-source="requestTableData[activeRequestKey]"
                 :pagination="false"
                 class="custom-editable-table"
                 rowKey="jsonKey">
          <template slot="parameterKeyTitle">
            <a-tooltip placement="top"
                       :mouseEnterDelay="0.3">
              <template slot="title">
                <span>消息头元素，例如：Content-Type</span>
              </template>
              <span>类型</span>
            </a-tooltip>
          </template>

          <template slot="parameterValueTitle">
            <a-tooltip placement="top"
                       :mouseEnterDelay="0.3">
              <template slot="title">
                <span>消息头元素内容，例如：application/json</span>
              </template>
              <span>内容</span>
            </a-tooltip>
          </template>

          <template slot="parameterName"
                    slot-scope="text, record">
            <div class="editable-input">
              <a-input v-model="record.parameterName"
                       placeholder="描述"></a-input>
            </div>
          </template>

          <template slot="parameterKey"
                    slot-scope="text, record">
            <div class="editable-input">
              <a-input v-model="record.parameterKey"
                       placeholder="请输入"
                       @change="onAddRow(record)"></a-input>
            </div>
          </template>

          <template slot="parameterValue"
                    slot-scope="text, record">
            <div class="editable-input">
              <a-input v-model="record.parameterValue"
                       placeholder="请输入"></a-input>
            </div>
          </template>

          <template slot="action"
                    slot-scope="text, record">
            <a-icon type="minus-circle"
                    @click="onDeleteRow(record, 'requestObject')"
                    v-if="record.isCanDelete"
                    style="color: #ff4d4f;" />
          </template>
        </a-table>
      </div>

      <!-- 接口响应对象 -->
      <a-divider orientation="left">接口响应</a-divider>
      <div style="width: 90%; margin: 10px auto 0 auto">
        <a-button type="primary"
                  size="small"
                  @click="onParseJson('responseObject')">
          <a-icon type="plus-square" />通过JSON生成
        </a-button>
        <a-table :columns="columns"
                 :data-source="dataList"
                 class="custom-editable-table drag"
                 rowKey="jsonKey"
                 :expanded-row-keys.sync="expandedRowKeys"
                 :pagination="false">
          <template slot="parameterKeyTitle">
            <a-tooltip placement="top"
                       :mouseEnterDelay="0.3">
              <template slot="title">
                <span>解析相应消息的所有数据字段</span>
              </template>
              <span>字段名称</span>
            </a-tooltip>
          </template>
          <template slot="parameterKey"
                    slot-scope="text, record">
            <div class="editable-input no-wrap drag"
                 v-if="!record.notEditable">
              <a-icon type="drag"
                      class="drag-icon"
                      @mousedown="(event)=>{onMouseHandle(event.target, 'listener')}"
                      @mouseup="(event)=>{onMouseHandle(event.target, 'remove')}" />
              <a-input v-model="record.parameterKey"
                       class="parameterKey"
                       @change="onChangeResponeParamKey"
                       placeholder="字段名称"></a-input>
            </div>
            <a-tag color="purple"
                   v-else>
              {{ record.parameterKey }}
            </a-tag>
          </template>
          <template slot="returnTypeTitle">
            <a-tooltip placement="top"
                       :mouseEnterDelay="0.3">
              <template slot="title">
                <span>需要指定响应消息体字段的类型，分别为消息(message)、数据(data)、状态码(code)、token(token)</span>
              </template>
              <span>数据解析</span>
            </a-tooltip>
          </template>

          <template slot="selfTypeTitle">
            <a-tooltip placement="top"
                       :mouseEnterDelay="0.3">
              <template slot="title">
                <span>字段类型设置，例：String，Object， Number</span>
              </template>
              <span>字段类型</span>
            </a-tooltip>
          </template>

          <template slot="parameterNameTitle">
            <a-tooltip placement="top"
                       :mouseEnterDelay="0.3">
              <template slot="title">
                <span>对应字段的显示名称</span>
              </template>
              <span>显示名称</span>
            </a-tooltip>
          </template>

          <template slot="parameterValueTitle">
            <a-tooltip placement="top"
                       :mouseEnterDelay="0.3">
              <template slot="title">
                <span>设置接口调用成功标识</span>
              </template>
              <span>成功值</span>
            </a-tooltip>
          </template>

          <template slot="returnType"
                    slot-scope="text, record">
            <a-dropdown :trigger="['click']"
                        v-if="!record.notEditable">
              <a class="normal-link"
                 @click="e => e.preventDefault()">
                {{ RETURN_TYPE_MAP[record.returnType || '0'] }}
              </a>
              <a-menu slot="overlay"
                      @click="(e)=>{onSelectReturnType(e, record)}">
                <a-menu-item key="0">
                  否
                </a-menu-item>
                <a-menu-item key="1"
                             :disabled="disableMSG">
                  消息
                </a-menu-item>
                <a-menu-item key="2"
                             :disabled="disableDATA">
                  数据
                </a-menu-item>
                <a-menu-item key="3"
                             :disabled="disableSTAUTS">
                  状态码
                </a-menu-item>
                <a-menu-item key="4"
                             :disabled="disableTOKEN">
                  token
                </a-menu-item>
              </a-menu>
            </a-dropdown>
          </template>
          <!-- 参数位置 -->
          <template slot="authPosition"
                    v-if="!record.notEditable"
                    slot-scope="text, record">
            <a-dropdown :trigger="['click']">
              <a class="normal-link"
                 @click="e => e.preventDefault()">
                {{ AUTH_POSITION_MAP[record.authPosition] }}
              </a>
              <a-menu slot="overlay"
                      @click="(e)=>{onSelectAuthPosition(e, record)}">
                <a-menu-item :key="name"
                             v-for="(value, name) in AUTH_POSITION_MAP">
                  {{ value }}
                </a-menu-item>
              </a-menu>
            </a-dropdown>
          </template>
          <!-- 参数名称 -->
          <template slot="authKey"
                    v-if="!record.notEditable"
                    slot-scope="text, record">
            <div class="editable-input">
              <a-input v-model="record.authKey"
                       placeholder="参数名称"></a-input>
            </div>
          </template>
          <template slot="parameterName"
                    slot-scope="text, record"
                    v-if="(!record.notEditable && !record.isRoot) && (!record.returnType || record.returnType === '-1')">
            <div class="editable-input">
              <a-input v-model="record.parameterName"
                       placeholder="显示名称"></a-input>
            </div>
          </template>
          <template slot="parameterValue"
                    slot-scope="text, record"
                    v-if="record.returnType == 3">
            <div class="editable-input">
              <a-input v-model="record.parameterValue"
                       placeholder="成功值"></a-input>
            </div>
          </template>
          <template slot="_selfType"
                    slot-scope="text, record">
            <!-- <a-tag :color="(text.includes('array') || text.includes('object')) ? '#87d068' : '#2db7f5'">{{ text }}</a-tag> -->
            <a-dropdown :trigger="['click']">
              <a class="ant-dropdown-link"
                 @click="e => e.preventDefault()">
                <span :style="{color: FIELD_TYPE_MAP[record.selfType]}">{{ record.selfType }}</span>
              </a>
              <a-menu slot="overlay"
                      @click="(e)=>{onSelectFieldType(e, record)}">
                <a-menu-item :key="name"
                             v-for="(value, name) in FIELD_TYPE_MAP">
                  {{ name }}
                </a-menu-item>
              </a-menu>
            </a-dropdown>
          </template>
          <template slot="action"
                    slot-scope="text, record">
            <div class="action-wrap"
                 v-if="!record.notEditable || record.isRoot">
              <template v-if="record.isRoot">
                <a-popover trigger="hover">
                  <template slot="content">
                    添加子节点
                  </template>
                  <a-icon type="plus-circle"
                          @click="onAddChildNode(record)"
                          class="plus" />
                </a-popover>
              </template>
              <template v-else-if="record.selfType === 'object'">
                <a-dropdown :trigger="['click']">
                  <a-icon type="plus-circle"
                          class="plus" />
                  <a-menu slot="overlay"
                          @click="({key})=>{ key === '1' ? onAddNearNode(record) : onAddChildNode(record)}">
                    <a-menu-item key="1">添加相邻节点</a-menu-item>
                    <a-menu-item key="2">添加子节点</a-menu-item>
                  </a-menu>
                </a-dropdown>
              </template>
              <template v-else>
                <a-popover trigger="hover">
                  <template slot="content">
                    添加相邻节点
                  </template>
                  <a-icon type="plus-circle"
                          @click="onAddNearNode(record)"
                          class="plus" />
                </a-popover>
              </template>
              <a-icon type="minus-circle"
                      v-if="!record.isRoot"
                      @click="onDeleteRow(record, 'responeObject')"
                      class="minus" />
            </div>
          </template>
          </transition-group></a-table>
      </div>
    </a-form-model>
    <!-- 解析JSON对象 -->
    <a-modal v-model="parseModal.visible"
             title="解析"
             @ok="onConfirm">
      <div style="text-align: right;margin-bottom: 5px;">
        <a-button type="primary"
                  size="small"
                  icon="align-center"
                  @click="onFormatJSON">
          格式化
        </a-button>
      </div>
      <a-form-model layout="horizontal"
                    :label-col="{span: 4}"
                    :wrapper-col="{span: 20}">
        <a-form-model-item label="消息对象">
          <a-textarea v-model="parseModal.content"
                      placeholder="{id:'',name: '', sex: ''}"
                      :auto-size="{ minRows: 15, maxRows: 20 }"></a-textarea>
        </a-form-model-item>
      </a-form-model>
    </a-modal>
  </div>
</template>

<script>
import { analysisJson, isJSON, parseSearchArgs, treeToList, getParentNodesByChild, uuid, arrayToJSON, requestReturnShowHandle, responeArrayHandle, onDragEventListener } from '../server'
import { paramsColumns, headerColumns, pathColumns, RETURN_TYPE_MAP, FIELD_TYPE_MAP, AUTH_POSITION_MAP } from '../config'
import _isEmpty from 'lodash/isEmpty'
import _cloneDeep from 'lodash/cloneDeep'
import _debounce from 'lodash/debounce'

export default {
  name: 'ApiCommon',
  inject: ['getApp'],
  props: {
    columns: {
      type: Array,
      default: () => []
    }
  },
  data () {
    return {
      timeKey: +new Date(),
      baseUrl: '',
      idNum: false,
      activeTabKey: '1',
      RETURN_TYPE_MAP: RETURN_TYPE_MAP,
      FIELD_TYPE_MAP: FIELD_TYPE_MAP,
      AUTH_POSITION_MAP: AUTH_POSITION_MAP,
      // 接口响应解析数据
      dataList: [],
      // 接口请求解析数据
      requestTableData: {
        params: [{ parameterKey: '', parameterValue: '', jsonKey: uuid() }],
        header: [{ parameterKey: '', parameterValue: '', jsonKey: uuid() }],
        path: []
      },
      requestTableColumns: {
        params: paramsColumns,
        header: headerColumns,
        path: pathColumns
      },
      expandedRowKeys: [],
      labelCol: { span: 6 },
      wrapperCol: { span: 12 },
      form: {
        requestMethod: '1',
        interfaceAddr: '',
        requestObject: '',
        responseObject: ''
      },
      rules: {
        interfaceAddr: [{
          required: true, message: '请输入接口地址', trigger: 'change'
        }]
      },
      parseModal: {
        visible: false,
        key: '',
        content: ''
      },
      disableMSG: false,
      disableSTAUTS: false,
      disableDATA: false,
      disableTOKEN: false
    }
  },
  computed: {
    activeRequestKey: function () {
      const requestKeyMap = new Map([
        ['1', 'params'],
        ['2', 'header'],
        ['3', 'path']
      ])
      return requestKeyMap.get(this.activeTabKey)
    },
    connectorData: function () {
      return this.getApp().connectorData
    }
  },
  watch: {
    connectorData: {
      handler: function (newData) {
        const _data = JSON.parse(JSON.stringify(newData))
        this.setApiInfo(_data)
      },
      immediate: true,
      deep: true
    },
    // 消息和状态码和数据只能选择一次
    dataList: {
      deep: true,
      immediate: true,
      handler: function (n, o) {
        if (!_isEmpty(n)) {
          let list = treeToList(_cloneDeep(n))
          let find = list.find(it => it.returnType == '1')
          let find2 = list.find(it => it.returnType == '3')
          let find3 = list.find(it => it.returnType == '2')
          let find4 = list.find(it => it.returnType == '4')
          this.disableMSG = !!find
          this.disableSTAUTS = !!find2
          this.disableDATA = !!find3
          this.disableTOKEN = !!find4
          this.timeKey = +new Date()
        }
      }
    }
  },
  methods: {
    onMouseHandle (target, type) {
      onDragEventListener(target, type, this.dataList, this.onChangeResponeParamKey)
    },
    setApiInfo (data) {
      const {
        connectorInterfaceVo = { requestMethod: '1' },
        responseParamterVo = {},
        requestParamterVo: {
          getParamters = [],
          paramterDataVoRequestList = [],
          headers = [],
          paths = []
        } = {}
      } = data?.interfaceAndParamterVo ? data.interfaceAndParamterVo : {}
      this.form = {
        ...connectorInterfaceVo
      }
      // 接口响应对象列表
      this.dataList = responeArrayHandle(responseParamterVo.paramterDataVoResponseList, 'parameterKey')
      // 请求消息对象列表
      const params = requestReturnShowHandle(getParamters)
      const paramterData = requestReturnShowHandle(paramterDataVoRequestList)
      this.requestTableData.params = connectorInterfaceVo.requestMethod == '1' ? params : paramterData
      this.requestTableData.header = requestReturnShowHandle(headers)
      this.requestTableData.path = paths
      this.activeTabKey = '1'
      // 默认自动展开根节点元素
      this.$nextTick(() => {
        this.expandedRowKeys = [this.dataList[0].jsonKey]
      })
    },
    // 格式化JSON字符串
    onFormatJSON () {
      try {
        if (!isJSON(this.parseModal.content)) {
          this.message.error('请输入合法的JSON字符串')
          return false
        }
        const content = JSON.stringify(JSON.parse(this.parseModal.content), null, 4)
        this.parseModal.content = content
      } catch (error) {
        this.message.error('请输入合法的JSON字符串')
      }
    },
    onAddRow: _debounce(function (record) {
      const list = this.requestTableData[this.activeRequestKey]
      const index = list.findIndex((row) => {
        return row.jsonKey === record.jsonKey
      })
      // 判断当前操作行是否是最后一行，最后一行则需要自动添加新一行
      if (index === list.length - 1) {
        record.isCanDelete = true
        list.push({ parameterKey: '', parameterValue: '', selfType: 'string', jsonKey: uuid() })
      }
      this.form.requestObject = JSON.stringify(arrayToJSON(list, 'parameterKey'))
    }, 500),
    // 显示解析消息对象弹框
    onParseJson (key) {
      this.parseModal.visible = true
      this.parseModal.key = key
      if (key === 'requestObject') {
        this.parseModal.content = this.form.requestObject
      } else {
        this.parseModal.content = this.form.responseObject
      }
      this.parseModal.content && this.onFormatJSON()
    },
    onConfirm () {
      if (!isJSON(this.parseModal.content)) {
        this.message.error('请输入合法的JSON字符串')
        return false
      }
      this.form[this.parseModal.key] = this.parseModal.content
      if (this.parseModal.key === 'requestObject') {
        this.requestTableData.params = analysisJson(JSON.parse(this.parseModal.content))
        this.requestTableData.params = requestReturnShowHandle(this.requestTableData.params)
      } else {
        this.dataList = analysisJson(JSON.parse(this.parseModal.content))
        this.dataList = responeArrayHandle(this.dataList)
      }
      this.form[this.parseModal.key] = this.parseModal.content
      this.parseModal.visible = false
    },
    // 解析接口地址中的 params 和 path
    onParseParams () {
      const { interfaceAddr, requestMethod } = this.form
      if (!interfaceAddr || requestMethod === '2') {
        return
      }
      const [url, query] = interfaceAddr.split('?')
      // 解析参数
      if (query) {
        let list = []
        let responseObject = parseSearchArgs('?' + query)
        if (!_isEmpty(responseObject)) {
          list = Object.keys(responseObject)
          this.requestTableData.params = list.map((item) => {
            return { parameterKey: item, parameterValue: '', jsonKey: uuid() }
          })
          this.onAddRow(this.requestTableData.params[0])
        }
      }
      // 解析PATH
      let reg = /{.*?}/g
      let pathList = url.match(reg) || []
      if (Array.isArray(pathList) && pathList.length > 0) {
        pathList = pathList.map(val => val.slice(1, val.length - 1))
      }
      this.requestTableData.path = pathList.map((item) => {
        return { parameterKey: item, parameterValue: '', jsonKey: uuid() }
      })
    },
    requestMethodChange () {
      this.activeTabKey = '1'
      for (const key in this.requestTableData) {
        this.requestTableData[key] = key === 'path' ? [] : [{ parameterKey: '', parameterValue: '', selfType: 'string', jsonKey: uuid() }]
      }
    },
    onChangeResponeParamKey: _debounce(function () {
      const list = this.dataList[0]?.children
      if (Array.isArray(list) && list.length > 0) {
        this.form.responseObject = JSON.stringify(arrayToJSON(list, 'parameterKey'))
      }
    }, 500),
    onSelectAuthPosition ({ key }, record) {
      this.$set(record, 'authPosition', key)
    },
    onSelectReturnType ({ key }, record) {
      // 数据或消息 清除 显示名称 成功值
      if (key == 'key' || key == '2') {
        record.parameterName = ''
        record.parameterValue = ''
      }
      // 状态码清除显示名称
      if (key == '3') {
        record.parameterName = ''
      }
      this.$set(record, 'returnType', key)
    },
    onSelectFieldType ({ key }, record) {
      if (key === record.selfType) {
        return false
      }
      // 选择的是object类型，清空当前子元素集合重新添加新的行
      if (key === 'object') {
        this.$set(record, 'children', [])
        this.onAddChildNode(record)
      }
      // 如果选择的不是object类型，则需要删除子元素集合
      if (key !== 'object' && record.children) {
        this.$delete(record, 'children')
      }
      // 选择array类型时，新增一条不可编辑的子元素行并且覆盖掉之前的子元素集合
      if (key === 'array') {
        const jsonKey = uuid()
        this.$set(record, 'children', [{ parameterKey: 'ITEMS', parameterValue: '', jsonKey: jsonKey, selfType: 'string', notEditable: true }])
        // 自动展开新增行
        this.expandedRowKeys.push(record.jsonKey)
      }
      this.$set(record, 'selfType', key)
    },
    onAddChildNode (record) {
      const _children = record.children || []
      const jsonKey = uuid()
      _children.push({ parameterKey: '', parameterValue: '', jsonKey: jsonKey, authPosition: '1', selfType: 'string' })
      this.$set(record, 'children', _children)
      this.inputFocus(jsonKey)
      // 自动展开新增行
      this.expandedRowKeys.push(record.jsonKey)
    },
    // 根据record 添加响应列表相邻节点
    onAddNearNode (record) {
      const parentNodes = getParentNodesByChild(this.dataList, record)
      const jsonKey = uuid()
      if (parentNodes.length === 0) {
        this.dataList.push({ parameterKey: '', parameterValue: '', jsonKey: jsonKey, authPosition: '1', selfType: 'string' })
      } else {
        const parentNode = parentNodes.pop()
        const _children = parentNode.children
        const index = _children.findIndex((node) => {
          return node.jsonKey === record.jsonKey
        })
        if (index > -1) {
          _children.splice((index + 1), 0, { parameterKey: '', parameterValue: '', jsonKey: jsonKey, authPosition: '1', selfType: 'string' })
          this.$set(parentNode, 'children', _children)
        }
      }
      this.inputFocus(jsonKey)
    },
    // 删除解析列表指定节点
    onDeleteRow (record, key) {
      let list = []
      if (key === 'requestObject') {
        list = this.requestTableData[this.activeRequestKey]
      } else {
        list = this.dataList
      }
      const parentNodes = getParentNodesByChild(list, record)
      if (parentNodes.length === 0) {
        const index = list.findIndex((row) => {
          return row.jsonKey === record.jsonKey
        })
        if (index > -1) {
          list.splice(index, 1)
        }
      } else {
        const parentNode = parentNodes.pop()
        const _children = parentNode.children
        const index = _children.findIndex((node) => {
          return node.jsonKey === record.jsonKey
        })
        if (index > -1) {
          _children.splice(index, 1)
          if (_children.length === 0) {
            this.$delete(parentNode, 'children')
          } else {
            this.$set(parentNode, 'children', _children)
          }
        }
      }
      if (key === 'requestObject') {
        this.form.requestObject = JSON.stringify(arrayToJSON(list, 'parameterKey'))
      } else {
        this.onChangeResponeParamKey()
      }
    },
    // 聚焦到指定的DOM元素
    inputFocus (jsonKey) {
      // 聚焦最新添加的文本输入框上
      this.$nextTick(() => {
        const domInput = document.querySelector(`.ant-table-row[data-row-key="${jsonKey}"] input`)
        domInput.focus()
      })
    }
  }
}
</script>

<style lang="less" scoped>
.custom-editable-table {
  margin-bottom: 30px;
  ::v-deep.ant-table-tbody td {
    padding: 5px 16px;
    border-bottom-color: #fafafa;
    &:has(.no-wrap) {
      white-space: nowrap;
    }
  }
  ::v-deep.ant-table-row {
    transition: 0.1s;
    &.dragging {
      background-color: #f9f0ff;
      box-shadow: 1px 1px 4px #d3adf7;
    }
    &:hover {
      td {
        position: relative;
        background-color: rgba(86, 87, 88, 0.04) !important;
      }
    }
  }
  ::v-deep.ant-table-thead th {
    background: transparent;
  }
  .editable-input {
    display: inline-block;
    width: 80%;
    &.drag {
      .drag-icon {
        &:hover {
          cursor: all-scroll;
        }
        transition: 0.3s;
        opacity: 0;
      }
      &:hover {
        .drag-icon {
          opacity: 1;
        }
      }
    }
    input {
      border: 1px solid transparent;
      border-radius: 0;
      height: 25px;
      background-color: transparent;
      padding: 4px;
      &:focus {
        box-shadow: none;
      }
      ::placeholder {
        color: rgba(16, 24, 40, 0.24);
      }
      &:hover,
      &:focus {
        border-bottom: 1px solid #40a9ff;
      }
    }
  }
  .normal-link {
    color: rgba(0, 0, 0, 0.65);
    &:hover {
      text-decoration: underline;
    }
  }
  .action-wrap {
    text-align: right;
    .anticon {
      cursor: pointer;
    }
    .plus {
      color: #43a047;
    }
    .minus {
      margin-left: 5px;
    }
  }
}
</style>